package com.xadrez.controlador;

import com.xadrez.Principal;
import com.xadrez.exception.PecaNaoPossuiPecaViewException;
import com.xadrez.exception.PecaProibidaException;
import com.xadrez.ia.IA;
import com.xadrez.ia.Jogada;
import com.xadrez.modelo.Jogador;
import com.xadrez.modelo.Peao;
import com.xadrez.modelo.Peca;
import com.xadrez.modelo.Posicao;
import com.xadrez.modelo.Rainha;
import com.xadrez.modelo.Rei;
import com.xadrez.modelo.Tabuleiro;
import com.xadrez.modelo.Torre;
import com.xadrez.view.JDPromocao;
import com.xadrez.view.MovimentoView;
import com.xadrez.view.PecaView;
import com.xadrez.view.Pintor;
import com.xadrez.view.TabuleiroView;
import com.xadrez.view.Tela;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

public class MovimentoControlador {

    private static boolean fezMovimento = false;
    //Teremos uma variavel para armazenar a peca que queremos mover.
    private static PecaView pecaAMover = null;

    // Esse método alterna entre a vez do jogador e a vez da IA
    public static void rodaAPartida(Jogador jogadorUm, Jogador jogadorDois) {
        Tabuleiro tabuleiro = Principal.getTabuleiro();

        tabuleiro.setJogadorDaVez(jogadorUm);
        boolean continua = true;

        while (continua) {
            try {
                Pintor.pintaCheck(jogadorUm, jogadorDois);
            } catch (PecaNaoPossuiPecaViewException ex) {
                ex.getMessage();
                System.exit(0);
            }

            if (tabuleiro.getJogadorDaVez() instanceof IA) {
                IA jogador = (IA) tabuleiro.getJogadorDaVez();
                realizaMovimentoDaIA(jogador);
                TabuleiroView.getInstance().repaint(); // Renderiza a tela
            } else {
                // Da tela surgirá o movimento humano, pois está dependente do clique. Então, ATENCAO! Está com warning mas não esta errado.
                while (!fezMovimento);
                fezMovimento = false;
            }
//            Som.getInstance().colocouPeca();
            continua = continuaPartida();
            tabuleiro.setJogadorDaVez(Principal.getTabuleiro().getJogadorAdversario());
        }

        System.out.println(">>>>>>>>>>>>>>>>>>>>>>VITORIA!");
    }

    private static boolean continuaPartida() {
        boolean continua = true;
        Tabuleiro tabuleiro = Principal.getTabuleiro();

        // VERIFICA CHECKMATE -----------------------------------------------------------------------
        if (tabuleiro.getJogadorAdversario().getReiDoJogador() != null) {
            if (tabuleiro.getJogadorAdversario().getReiDoJogador().isInCheck()) {
                if (tabuleiro.getJogadorAdversario().getReiDoJogador().isInCheckMate()) {
                    tabuleiro.getJogadorAdversario().addVitoria();
                    continua = false;
                    JOptionPane.showConfirmDialog(null, "Xeque-mate!");
                }
            }
        } else {
            JOptionPane.showConfirmDialog(null, "Xeque-mate!");
        }
        if (tabuleiro.getJogadorDaVez().getReiDoJogador().isInCheck()) {
            tabuleiro.getJogadorDaVez().getReiDoJogador().checkContinues();
        }

        // VERIFICA EMPATE --------------------------------------------------------------------------
        if (Principal.getTabuleiro().empate()) {
            Principal.getTabuleiro().getJogadorDaVez().addVitoria();
            Principal.getTabuleiro().getJogadorDaVez().addVitoria();
            // System.out.print(">>>>>>>>>>>>>>>>>>>>>>EMPATE");
            continua = false;
            JOptionPane.showConfirmDialog(null, "Empate");
        }

        return continua;
    }

    //Movimenta a peca do jogador humano. Trabalha junto com a leitura do mouse pela classe Tela.
    public static void realizaMovimentoHumano(MouseEvent e) {
        //1. Recuperamos a peca a qual o jogador supostamente clicou.
        PecaView pecaView = TabuleiroView.getInstance().buscaPeca(e.getX(), e.getY());

        if ((pecaView != null)&&(pecaAMover != null)&&(pecaView.getPeca() instanceof Torre)&&(pecaAMover.getPeca() instanceof Rei)){
             if((((Rei) pecaAMover.getPeca()).podeRoqueGrande())||((Rei) pecaAMover.getPeca()).podeRoquePequeno()){
            
                int status = 1;
                int yRei = 2;
                int yTorre =3;
                if (pecaView.getPeca().getPosicaoNoTabuleiro().getY() == 7){
                    status = 0;
                    yRei=6;
                    yTorre=5;
                }
                // no tabuleiro real
                Posicao posicao = new Posicao(pecaAMover.getPeca().getPosicaoNoTabuleiro().getX(),pecaAMover.getPeca().getPosicaoNoTabuleiro().getY(),status);
                pecaAMover.getPeca().deslocaPeca(posicao);
                
                // na interface
                Posicao posicaoView = TabuleiroView.getInstance().getPosicaoNaView(new Posicao(pecaAMover.getPeca().getPosicaoNoTabuleiro().getX(), yRei));
                Component c = TabuleiroView.getInstance().findComponentAt(posicaoView.getX(),posicaoView.getY());
                MovimentoView.move(pecaAMover,c);
                TabuleiroView.getInstance().repaint();
                
                posicaoView = TabuleiroView.getInstance().getPosicaoNaView(new Posicao(pecaView.getPeca().getPosicaoNoTabuleiro().getX(), yTorre));
                c = TabuleiroView.getInstance().findComponentAt(posicaoView.getX(),posicaoView.getY());
                MovimentoView.move(pecaView,c);
             }
        }else if (pecaView != null && pecaView.getPeca().getJogador().equals(Principal.getTabuleiro().getJogadorDaVez())) {
            //2. O jogador clicou numa peça dele
            //3. Se nao existia nenhuma peca a mover armazenada na varial, adicionamos essa, se essa for uma peca do jogador.
            pecaAMover = pecaView;

            //Desenharemos a ação da peca no tabuleiro(view)
            MovimentoView.desenhaAcaoDoMouse(e);
            


//            Som.getInstance().tocouEmPeca();
        } else {
            //2. Se chegou aqui quer dizer que ele clicou num espaço vazio ou numa peça inimiga
            if (pecaAMover != null) {
                //3. Se pecaAMover diferente de null, significa que tem uma peca esperando para ser movida...

                //4. Vamos recuperar a posicao no tabuleiro real obtida pelo clique do mouse e depois move-la
                Posicao posicao = TabuleiroView.getInstance().getPosicaoReal(new Posicao(e.getX(), e.getY()));
                boolean moveu = pecaAMover.getPeca().deslocaPeca(posicao);

                //Desenharemos a ação da peca no tabuleiro(view)
                MovimentoView.desenhaAcaoDoMouse(e);
                TabuleiroView.getInstance().repaint();
                if (moveu) {
                    if (pecaAMover.getPeca() instanceof Peao) {
                        if (((Peao) pecaAMover.getPeca()).upar()) {

                            JDPromocao telaPromocao = new JDPromocao(Tela.getFrame());
                            telaPromocao.setLocationRelativeTo(Tela.getFrame());
                            telaPromocao.setModal(true);
                            telaPromocao.setVisible(true);


                            Class c = telaPromocao.getPecaEscolhida();
                            Peca peca = null;
                            try {
                                peca = Principal.getTabuleiro().promocao(pecaAMover.getPeca(), c);
                            } catch (PecaProibidaException ex) {
                                ex.printStackTrace();
                                Logger.getLogger(MovimentoControlador.class.getName()).log(Level.SEVERE, null, ex);
                            } catch (InstantiationException ex) {
                                ex.printStackTrace();
                                Logger.getLogger(MovimentoControlador.class.getName()).log(Level.SEVERE, null, ex);
                            } catch (IllegalAccessException ex) {
                                ex.printStackTrace();
                                Logger.getLogger(MovimentoControlador.class.getName()).log(Level.SEVERE, null, ex);
                            }
                            TabuleiroView.getInstance().promover(peca);
                            TabuleiroView.getInstance().repaint();
                        }
                    }
                    
                    //5. Caso tenhamos conseguido movimentar a peca, agora a variavel pecaAMover, volta a ser null
                    pecaAMover = null;
                    fezMovimento = true;

                }
            }
        }
    }

    public static void realizaMovimentoDaIA(IA jogador) {
        Jogada jogada = jogador.jogar();
        MovimentoView.desenhaIAMovendo(jogada.getPosicao(), jogada.getPosicaoAntiga());
        if (jogada.isPromocao()) {
            try {
                jogada.setPeca(Principal.getTabuleiro().promocao(jogada.getPeca(), Rainha.class));
            } catch (PecaProibidaException ex) {
                Logger.getLogger(MovimentoControlador.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InstantiationException ex) {
                Logger.getLogger(MovimentoControlador.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(MovimentoControlador.class.getName()).log(Level.SEVERE, null, ex);
            }
            TabuleiroView.getInstance().promover(jogada.getPeca());
        }
    }
}
